#include "antistress.h"
#include "QSettings"
#include "QDebug"

#include "analyser.h"
#include "utils/myMath.h"
Antistress::Antistress(QWidget *parent)
    : QMainWindow(parent)
{
	ui.setupUi(this);

	setWindowTitle("Antistress");
        // Retrieve settings
        updateSettings();

		m_home = NULL;
		m_pause = NULL;
		m_work = NULL;
		m_settings = NULL;

        workTimer = new QTimer(this);
        connect(workTimer, SIGNAL(timeout()), this, SLOT(workEnd()));

        pauseTimer = new QTimer(this);
        connect(pauseTimer, SIGNAL(timeout()), this, SLOT(pauseEnd()));

        refreshTimer = new QTimer(this);

	loadNetworkFile(":/network");

	// initialize the controller
	m_usbsensor= new OakSensorVisual();
	m_usbsensor->startCapture();

	m_neuralTimer = new QTimer(this);
	connect(m_neuralTimer, SIGNAL(timeout()), this, SLOT(runningNeuralNetwork()));

	selectHomeWidget();
}

Antistress::~Antistress()
{
	//TODO: delete
}

void Antistress::exit(){
	qApp->exit();
}

void Antistress::resetCentralWidget(){
	if(centralWidget()!=NULL) {
		delete centralWidget();
		m_home = NULL;
		m_pause = NULL;
		m_work = NULL;
		m_settings = NULL;
		refreshTimer->disconnect();
	}
}
void Antistress::selectPauseWidget(){
	resetCentralWidget();
	m_pause = new Pause();
	connect(m_pause,SIGNAL(stopClicked()),this,SLOT(selectHomeWidget()));
    connect(refreshTimer, SIGNAL(timeout()), this, SLOT(refreshWP()));

	 disconnect(this, SIGNAL(refresh(int)), m_pause, SLOT(refresh(int)));
        connect(this, SIGNAL(refresh(int)), m_pause, SLOT(refresh(int)) ,Qt::UniqueConnection);

		sec = 60*lengthPause+lengthSecPause;
        emit refresh(sec);
        pauseTimer->start(1000* (60*lengthPause+lengthSecPause));
        refreshTimer->start(1000);

	m_pause->setMove(QPixmap(":/mid"));
	setCentralWidget(m_pause);
	m_state = INITIALIZE;
	m_cycle = 6;
	m_neuralTimer->start(100);
}
void Antistress::selectSettingsWidget() {
	resetCentralWidget();
	refreshTimer->disconnect();
	m_settings = new Settings();
	connect(m_settings,SIGNAL(backToHomeClicked()),this,SLOT(selectHomeWidget()));
    connect(m_settings,SIGNAL(settingsClicked()),this,SLOT(updateSettings()));

	setCentralWidget(m_settings);

}
void Antistress::selectWorkWidget() {
	//m_neuralTimer->stop();

	resetCentralWidget();
	m_work = new Work(this);
	connect(m_work,SIGNAL(stopClicked()),this,SLOT(selectHomeWidget()));
        connect(refreshTimer, SIGNAL(timeout()), this, SLOT(refreshWP()),Qt::UniqueConnection);
        disconnect(this, SIGNAL(refresh(int)), m_work, SLOT(refresh(int)));
        connect(this, SIGNAL(refresh(int)), m_work, SLOT(refresh(int)));

		sec = 3600*freqPauseH + 60*freqPauseMin+freqPauseSec;
        emit refresh(sec);
        workTimer->start(1000* (freqPauseH*3600 + freqPauseMin*60+freqPauseSec));
    refreshTimer->start(1000);

	setCentralWidget(m_work);
}
void Antistress::selectHomeWidget() {
	resetCentralWidget();
	m_home = new Home(this);
	connect(m_home,SIGNAL(startClicked()),this,SLOT(selectWorkWidget()));
	connect(m_home,SIGNAL(exitClicked()),this,SLOT(exit()));
	connect(m_home,SIGNAL(settingsClicked()),this,SLOT(selectSettingsWidget()));

    workTimer->stop();
    pauseTimer->stop();

	setCentralWidget(m_home);
}

void Antistress::updateSettings() {
    QSettings settings("../settings.ini", QSettings::IniFormat);
    freqPauseH = settings.value("freqPauseH",1).toInt();
    freqPauseMin = settings.value("freqPauseMin",30).toInt();
	freqPauseSec = settings.value("freqPauseSec",0).toInt();
    lengthPause = settings.value("pauseLength",5).toInt();
	lengthSecPause = settings.value("pauseSecLength",0).toInt();
}

void Antistress::workEnd() {
    qDebug()<< "Work End";
	workTimer->stop();
    selectPauseWidget();
}

void Antistress::pauseEnd() {
    qDebug()<< "Pause End";
	pauseTimer->stop();
	m_neuralTimer->stop();
    selectWorkWidget();
}

void Antistress::refreshWP() {
    if (sec>0)
        sec--;
    emit refresh(sec);
}

void Antistress::loadNetworkFile(QString _file){
	QFile file(_file);

    // Open the file
    if (!file.open(QFile::ReadOnly))
        return;

    QTextStream stream(&file);
    QString line = stream.readLine();

    // Check file type
    if (line.compare("FENNIX Network Weights File") != 0)
    {
        throw "Not a FENNIX file";
        return;
    }

    // Go to the first Layer
    while (stream.readLine().compare("Indexes") != 0);

    // Get the number of neurons
    int layers = 0;
    int neurons[5]; // Max layers at this moment

    while (!stream.readLine().isEmpty())
    {
        line = stream.readLine();
        neurons[layers] = line.trimmed().split("\t").size();
        layers++;
    }

    // Create the network
    m_network.createNetwork(layers, neurons);

    // Set the weights
    int i=0;
    while (!(line = stream.readLine()).isNull())
    {
        QStringList list = line.trimmed().split("\t");
        for (int j=0; j<list.size(); j++)
            m_network.setWeight(i, j, ((QString) list.at(j)).toDouble());

        i++;
    }
}


void Antistress::runningNeuralNetwork() {
	if (m_neuralTimer->isActive() && m_cycle>0)
    {
    	double outVal[3];
		double inVal[10];
		

		short initial[nbr];
		double modified [nbr];
		
		//Axe Y
		m_usbsensor->getBufferArray(2, initial, nbr);
		for (int i=0; i<nbr; i++){
            modified[i] = (initial[i]*(0.001));
		}
		inVal[0] = Math::dmin(modified, nbr);
		inVal[1] = Math::dmax(modified, nbr);
		inVal[2] = Math::dmean(modified, nbr);

		//Axe Z
        m_usbsensor->getBufferArray(3, initial, nbr);
		for (int i=0; i<nbr; i++){
            modified[i] = (initial[i]*(0.001));
		}
		inVal[3] = Math::dmin(modified, nbr);
		inVal[4] = Math::dmax(modified, nbr);
		inVal[5] = Math::dmean(modified, nbr);

	    // Feed the neural network with the values
		if(m_network.runNetwork(inVal, outVal)){
			for(int i = 0;i<3;i++){
				outVal[i]= 100 * (outVal[i]);
			}
			//qDebug()<< QString("Bas: %1 Mid: %2 Haut: %3").arg((outVal[0])).arg((outVal[1])).arg((outVal[2]));
		
			PauseStateEnum current;
			if(outVal[0]>75 && outVal[1]<75 && outVal[2]<75) {
				//qDebug()<<"BAS";
				current = DOWN;
			}
			else if(outVal[0]<75 && outVal[1]>75 && outVal[2]<75) {
				//qDebug()<<"MID";
				current = MID;
			}
			else if(outVal[0]<75 && outVal[1]<75 && outVal[2]>75) {
				//qDebug()<<"HAUT";
				current = HIGH;
			}else {
				//qDebug()<<"AUCUN";
				current = ANY;
			}
			switch(m_state){
			case INITIALIZE:
				if(current==MID){
					m_pause->setMove(QPixmap(":/mid_down"));
					qDebug()<<" Next BAS";
					m_state=DOWN;
				}
				break;
			case DOWN:
				if(current==DOWN){
					m_cycle--;
					if(m_cycle<=0){
						qDebug()<<" Vous avez fini de destresser";
						pauseEnd();
					}else{
						m_pause->setMove(QPixmap(":/down_high"));
						qDebug()<<" Next HIGH";
						m_state=HIGH;
					}
				}
				break;
			case MID:
				break;
			case HIGH:
				if(current==HIGH){
					m_pause->setMove(QPixmap(":/high_down"));
					qDebug()<<" Next BAS";
					m_state=DOWN;
				}
				break;
			
			}
			
		}
/*        m_ui->progressBar->setValue(100 * (outVal[0]));
        m_ui->progressBar_2->setValue(100 * (outVal[1]));
		m_ui->progressBar_3->setValue(100 * (outVal[2]));
  */          
   }
}


